1
Il divario prestazionale: perché estendere NumPy?
AI018Lesson 5
00:00

Mentre NumPy è basato su C, alcuni algoritmi ad elevata intensità computazionale raggiungono un muro della vettorizzazione. Ciò avviene quando la latenza intrinseca della natura dinamica di Python supera i vantaggi dell'astrazione di alto livello.

1. L'imposta dell'interprete e il boxing

Ogni iterazione in un ciclo Python standard richiede controllo dei tipi dinamico e conteggio dei riferimenti. Anche quando si utilizzano scalari NumPy, il "boxing" dei dati grezzi in oggetti Python crea un grosso collo di bottiglia per funzioni come $\text{logit}(p) = \log(p/(1-p))$. Gestire casi limite in C è drasticamente più veloce:

>>> logit(0) -> -inf
>>> logit(1) -> inf
>>> logit(2) -> nan
>>> logit(-2) -> nan

2. Espansione temporanea degli array

Espressioni puramente NumPy creano buffer di memoria temporanei per ogni operazione secondaria. Estendere tramite l'API C permette Fusione kernel, dove la trasformazione logit viene calcolata in un'unica passata senza sovraccarico di memoria ausiliaria.

3. Dipendenze spaziali

Operazioni che coinvolgono schemi di accesso ai vicini, come lo stencil 2D:

$$B(I, J) = A(I, J) + (A(I-1, J) + A(I+1, J) + A(I, J-1) + A(I, J+1)) \cdot 0.5D0 + (A(I-1, J-1) + A(I-1, J+1) + A(I+1, J-1) + A(I+1, J+1)) \cdot 0.25D0$$

sono difficili da esprimere in modo efficiente tramite slicing senza copie di memoria ridondanti. Le estensioni C consentono un'aritmetica diretta e allineata alla cache con puntatori.

main.py
TERMINALbash — 80x24
> Ready. Click "Run" to execute.
>